package com.fc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fc.context.BaseContext;
import com.fc.dto.LogisticsCompleteDTO;
import com.fc.dto.LogisticsDTO;
import com.fc.dto.pageQuery.LogisticsPageQueryDTO;
import com.fc.entity.Logistics;
import com.fc.entity.Route;
import com.fc.entity.StatusLog;
import com.fc.enums.TransportStatus;
import com.fc.enums.TransportType;
import com.fc.exception.LogisticsiException;
import com.fc.mapper.LogisticsMapper;
import com.fc.mapper.RouteMapper;
import com.fc.mapper.StatusLogMapper;
import com.fc.result.PageResult;
import com.fc.service.ILogisticsService;
import com.fc.utils.MonthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class LogisticsServiceImpl extends ServiceImpl<LogisticsMapper, Logistics> implements ILogisticsService {

    @Autowired
    private RouteMapper routeMapper;


    @Autowired
    private StatusLogMapper statusLogMapper;

    @Autowired
    @Qualifier("bigDecimalRedisTemplate")
    private RedisTemplate<String, BigDecimal> bigDecimalRedisTemplate;

    @Override
    public Long commit(LogisticsDTO logisticsDTO) {
        // 校验必填字段
        if (logisticsDTO.getRouteId() == null || logisticsDTO.getVehiclePlate() == null) {
            throw new LogisticsiException("路线ID和车牌号不能为空");
        }

        Logistics logistics = BeanUtil.copyProperties(logisticsDTO, Logistics.class);

        Route route = routeMapper.selectById(logisticsDTO.getRouteId());
        if (route == null) {
            throw new LogisticsiException("路线不存在");
        }

        //tips：接收司机传递过来的方式
        //logistics.setTransportType(route.getTransportType());
        if (logisticsDTO.getTransportType() == TransportType.SINGLE.getCode()) {
            logistics.setPrice(route.getSinglePrice());
            logistics.setRate(route.getSingleRate());
        } else if (logisticsDTO.getTransportType() == TransportType.BILATERAL.getCode()) {
            logistics.setPrice(route.getBilateralPrice());
            logistics.setRate(route.getBilateralRate());
        }
        if (route.getCoefficient() != null) {
            logistics.setCoefficient(route.getCoefficient());
        }
        // 设置初始状态为 "待出发"
        logistics.setStatus(TransportStatus.STARTED.getCode());
        logistics.setDriverId(BaseContext.getCurrentId());

        logistics.setDepartureTime(LocalDateTime.now());

        save(logistics);
        return logistics.getId();
    }

    @Override
    public void updateLogistics(LogisticsDTO logisticsDTO) {
        Logistics logistics = getById(logisticsDTO.getId());
        if (logistics.getStatus().equals(TransportStatus.COMPLETED.getCode())) {
            throw new LogisticsiException("运输已完成，无法修改信息");
        }
        updateById(BeanUtil.copyProperties(logisticsDTO, Logistics.class));
    }

    @Transactional
    @Override
    public void complete(LogisticsCompleteDTO logisticsCompleteDTO) {
        List<String> evidenceImages = logisticsCompleteDTO.getEvidenceImages();
        Long id = logisticsCompleteDTO.getId();
        Logistics logistics = getById(id);
        if (logistics == null) {
            throw new LogisticsiException("物流信息不存在");
        }
        // 校验状态是否可以完成
        if (logistics.getStatus() != TransportStatus.STARTED.getCode()) {
            throw new LogisticsiException("状态异常");
        }

        // 校验是否已经上传图片
        if (evidenceImages == null || evidenceImages.isEmpty()) {
            throw new LogisticsiException("未提交证明截图，无法完成当前运输");
        }

        logistics.setEvidenceImages(evidenceImages);
        logistics.setStatus(TransportStatus.COMPLETED.getCode());
        logistics.setArrivalTime(LocalDateTime.now());

        // 记录状态变更日志
        saveStatusChangeLog(id, BaseContext.getCurrentId(), TransportStatus.STARTED, TransportStatus.COMPLETED);

        updateById(logistics);

        BigDecimal amount = logistics.getRate().multiply(logistics.getCoefficient());
        updateDriverDailyIncomeInRedis(logistics.getDriverId(), amount);
    }


    @Override
    public PageResult listLogistics(LogisticsPageQueryDTO logisticsPageQueryDTO) {
        Page<Logistics> page = new Page<>(logisticsPageQueryDTO.getPageNum(), logisticsPageQueryDTO.getPageSize());
        String vehiclePlate = logisticsPageQueryDTO.getVehiclePlate();
        Integer cargoType = logisticsPageQueryDTO.getCargoType();
        Integer status = logisticsPageQueryDTO.getStatus();
        Long driverId = logisticsPageQueryDTO.getDriverId();
        LocalDateTime startDate = logisticsPageQueryDTO.getStartDate();
        LocalDateTime endDate = logisticsPageQueryDTO.getEndDate();

        Integer month = logisticsPageQueryDTO.getMonth();
        boolean flag= month != null && (month > 0 && month < 13);

        Page<Logistics> pageResult = lambdaQuery()

                .like(vehiclePlate != null, Logistics::getVehiclePlate, vehiclePlate)
                .eq(cargoType != null, Logistics::getCargoType, cargoType)
                .eq(status != null, Logistics::getStatus, status)
                .eq(driverId != null, Logistics::getDriverId, driverId)
                .between(startDate != null && endDate != null, Logistics::getDepartureTime, startDate, endDate)
                .between(flag,Logistics::getDepartureTime,MonthUtil.getMonthStart(month),MonthUtil.getMonthEnd(month))
                .orderByDesc(Logistics::getDepartureTime)
                .orderByDesc(Logistics::getArrivalTime)
                .page(page);
        return new PageResult(pageResult.getTotal(), pageResult.getRecords());
    }

    /**
     * 改变状态
     *
     * @param logisticsId
     * @param fromStatus
     * @param toStatus
     */
    private void saveStatusChangeLog(Long logisticsId, Long driverId, TransportStatus fromStatus, TransportStatus toStatus) {
        StatusLog statusChangeLog = new StatusLog();
        statusChangeLog.setLogisticsId(logisticsId);
        statusChangeLog.setDriverId(driverId);
        statusChangeLog.setFromStatus(fromStatus.getDescription());
        statusChangeLog.setToStatus(toStatus.getDescription());
        statusChangeLog.setChangeTime(LocalDateTime.now());
        statusLogMapper.insert(statusChangeLog);
    }

    /**
     * 根据用户id和时间区域查询物流信息
     *
     * @param driverId
     * @param start
     * @param end
     * @return
     */
    public List<Logistics> getByDriverIdAndTimeRange(Long driverId, LocalDateTime start, LocalDateTime end) {
        return list(new LambdaQueryWrapper<Logistics>()
                .eq(Logistics::getDriverId, driverId)
                .eq(Logistics::getStatus, TransportStatus.COMPLETED.getCode())
                .between(Logistics::getArrivalTime, start, end)
        );
    }

    /**
     * 计算司机日常收入（Redis缓存）
     *
     * @param driverId 司机ID
     * @param amount   收入金额
     */
    private void updateDriverDailyIncomeInRedis(Long driverId, BigDecimal amount) {
        // 获取当前日期（格式：YYYYMMDD）
        String date = LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE); // 例如：20240405
        String key = "driver:income:day:" + driverId + ":" + date;
        BigDecimal currentIncome = bigDecimalRedisTemplate.opsForValue().get(key);
        if (currentIncome == null) {
            bigDecimalRedisTemplate.opsForValue().set(key, amount);
        } else {
            bigDecimalRedisTemplate.opsForValue().set(key, currentIncome.add(amount));
        }
        // 设置过期时间为当天剩余时间 + 24 小时（确保覆盖到自然日结束）
        long expireTime = getRemainingTimeUntilMidnight(); // 计算到当天 24:00 的剩余时间（毫秒）
        bigDecimalRedisTemplate.expire(key, expireTime, TimeUnit.MILLISECONDS);
    }

    private long getRemainingTimeUntilMidnight() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime midnight = now.toLocalDate().plusDays(1).atStartOfDay(); // 当天 24:00
        Duration duration = Duration.between(now, midnight);
        return duration.toMillis();
    }

}
